<?php
declare(strict_types=1);

namespace app\service;

use app\model\{MerchantApplication, PlatformConfig};
use EasyWeChat\Factory;
use think\facade\Log;

class WechatService extends BaseService
{
    protected $config;
    protected $merchant_id;
    protected $miniApp;
    protected $officialAccount;
    
    public function __construct($merchant_id)
    {
        $this->merchant_id = $merchant_id;
        $this->initConfig();
    }
    
    /**
     * 初始化配置
     */
    protected function initConfig()
    {
        // 获取商家应用配置
        $appConfig = MerchantApplication::where([
            'merchant_id' => $this->merchant_id,
            'application_type' => 1 // 微信小程序
        ])->find();
        
        $mpConfig = MerchantApplication::where([
            'merchant_id' => $this->merchant_id,
            'application_type' => 2 // 公众号
        ])->find();
        
        // 小程序配置
        $this->config['mini_program'] = [
            'app_id' => $appConfig->app_id ?? '',
            'secret' => $appConfig->app_secret ?? '',
            'response_type' => 'array',
            'log' => [
                'level' => 'debug',
                'file' => runtime_path() . 'log/wechat.log',
            ],
        ];
        
        // 公众号配置
        $this->config['official_account'] = [
            'app_id' => $mpConfig->app_id ?? '',
            'secret' => $mpConfig->app_secret ?? '',
            'token' => $mpConfig->token ?? '',
            'aes_key' => $mpConfig->encoding_aes_key ?? '',
            'response_type' => 'array',
            'log' => [
                'level' => 'debug',
                'file' => runtime_path() . 'log/wechat.log',
            ],
        ];
    }
    
    /**
     * 获取小程序实例
     */
    protected function getMiniApp()
    {
        if (!$this->miniApp) {
            $this->miniApp = Factory::miniProgram($this->config['mini_program']);
        }
        return $this->miniApp;
    }
    
    /**
     * 获取公众号实例
     */
    protected function getOfficialAccount()
    {
        if (!$this->officialAccount) {
            $this->officialAccount = Factory::officialAccount($this->config['official_account']);
        }
        return $this->officialAccount;
    }
    
    /**
     * 发送小程序订阅消息
     */
    public function sendSubscribeMessage($params)
    {
        try {
            $app = $this->getMiniApp();
            $result = $app->subscribe_message->send([
                'touser' => $params['touser'],
                'template_id' => $params['template_id'],
                'page' => $params['page'],
                'data' => $params['data']
            ]);
            
            if ($result['errcode'] === 0) {
                return true;
            }
            
            Log::error('发送小程序订阅消息失败', [
                'params' => $params,
                'result' => $result
            ]);
            return false;
        } catch (\Exception $e) {
            Log::error('发送小程序订阅消息异常: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 发送公众号模板消息
     */
    public function sendTemplateMessage($params)
    {
        try {
            $app = $this->getOfficialAccount();
            $result = $app->template_message->send([
                'touser' => $params['touser'],
                'template_id' => $params['template_id'],
                'url' => $params['url'],
                'data' => $params['data']
            ]);
            
            if ($result['errcode'] === 0) {
                return true;
            }
            
            Log::error('发送公众号模板消息失败', [
                'params' => $params,
                'result' => $result
            ]);
            return false;
        } catch (\Exception $e) {
            Log::error('发送公众号模板消息异常: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 企业付款到零钱
     */
    public function transfer($params)
    {
        try {
            $app = $this->getMiniApp();
            $result = $app->transfer->toBalance([
                'partner_trade_no' => $params['out_trade_no'],
                'openid' => $params['openid'],
                'amount' => $params['amount'],
                'desc' => $params['desc']
            ]);
            
            if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
                return true;
            }
            
            Log::error('企业付款到零钱失败', [
                'params' => $params,
                'result' => $result
            ]);
            return false;
        } catch (\Exception $e) {
            Log::error('企业付款到零钱异常: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 退款
     */
    public function refund($params)
    {
        try {
            $app = $this->getMiniApp();
            $result = $app->refund->byOutTradeNumber(
                $params['out_trade_no'],
                date('YmdHis') . mt_rand(1000, 9999),
                $params['total_fee'],
                $params['refund_fee'],
                [
                    'refund_desc' => $params['refund_desc']
                ]
            );
            
            if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
                return true;
            }
            
            Log::error('微信退款失败', [
                'params' => $params,
                'result' => $result
            ]);
            return false;
        } catch (\Exception $e) {
            Log::error('微信退款异常: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 生成小程序码
     */
    public function createMiniQrcode($scene, $page)
    {
        $app = Factory::miniProgram($this->config['mini_program']);
        
        try {
            return $app->app_code->getUnlimit($scene, [
                'page' => $page
            ]);
        } catch (\Exception $e) {
            return false;
        }
    }
    
    /**
     * 生成公众号二维码
     */
    public function createMpQrcode($scene)
    {
        $app = Factory::officialAccount($this->config['official_account']);
        
        try {
            $result = $app->qrcode->temporary($scene, config('invite.qrcode_expire'));
            return $app->qrcode->url($result['ticket']);
        } catch (\Exception $e) {
            return false;
        }
    }
    
    /**
     * 获取企业微信实例
     */
    protected function getWorkApp($config)
    {
        return Factory::work([
            'corp_id' => $config['corp_id'],
            'agent_id' => $config['agent_id'],
            'secret' => $config['secret'],
        ]);
    }
    
    /**
     * 生成企业微信群聊二维码
     */
    public function createWorkChatQrcode($config)
    {
        try {
            $app = $this->getWorkApp($config);
            
            // 创建群聊
            $chatInfo = $app->external_contact->createGroupChat([
                'name' => '用户交流群',
                'owner' => $config['owner_userid'],
                'userlist' => [$config['owner_userid']],
                'chat_id' => uniqid('chat_')
            ]);
            
            if (!isset($chatInfo['chat_id'])) {
                Log::error('创建企业微信群聊失败', ['result' => $chatInfo]);
                return false;
            }
            
            // 获取群二维码
            $result = $app->external_contact->getGroupQrcode($chatInfo['chat_id']);
            
            if (!isset($result['qr_code'])) {
                Log::error('获取企业微信群二维码失败', ['result' => $result]);
                return false;
            }
            
            return $result['qr_code'];
        } catch (\Exception $e) {
            Log::error('生成企业微信群二维码异常: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 获取企业微信成员信息
     */
    public function getWorkUserInfo($config, $userId)
    {
        try {
            $app = $this->getWorkApp($config);
            return $app->user->get($userId);
        } catch (\Exception $e) {
            Log::error('获取企业微信成员信息异常: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 解散企业微信群聊
     */
    public function dismissWorkChat($config, $chatId)
    {
        try {
            $app = $this->getWorkApp($config);
            $result = $app->external_contact->dismissChat($chatId);
            
            if ($result['errcode'] === 0) {
                return true;
            }
            
            Log::error('解散企业微信群聊失败', ['result' => $result]);
            return false;
        } catch (\Exception $e) {
            Log::error('解散企业微信群聊异常: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 获取客户群进群二维码
     * @param array $config 企业微信配置
     * @param array $params 请求参数
     * @return array|bool
     */
    public function getJoinQrcode($config, $params)
    {
        try {
            $app = $this->getWorkApp($config);
            $result = $app->external_contact->createJoinWay([
                'scene' => 2, // 2-群的二维码插件
                'remark' => $params['remark'] ?? '',
                'auto_create_room' => $params['auto_create_room'] ?? 0,
                'room_base_name' => $params['room_base_name'] ?? '',
                'room_base_id' => $params['room_base_id'] ?? null,
                'chat_id_list' => $params['chat_id_list'] ?? [],
                'state' => $params['state'] ?? ''
            ]);
            
            if ($result['errcode'] === 0) {
                return $result;
            }
            
            Log::error('获取企业微信群二维码失败', ['result' => $result]);
            return false;
        } catch (\Exception $e) {
            Log::error('获取企业微信群二维码异常: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 获取公众号网页授权链接
     */
    public function getMpAuthUrl(string $state): string
    {
        $redirectUri = urlencode(request()->domain() . '/user/mp_login');
        
        return sprintf(
            'https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=%s#wechat_redirect',
            $this->config['official_account']['app_id'],
            $redirectUri,
            $state
        );
    }
    
    /**
     * 获取公众号access_token和openid
     */
    public function getMpAccessToken(string $code): array
    {
        $url = sprintf(
            'https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code',
            $this->config['official_account']['app_id'],
            $this->config['official_account']['secret'],
            $code
        );

        $response = $this->httpGet($url);
        return json_decode($response, true) ?: [];
    }
    
    /**
     * 获取公众号用户信息
     */
    public function getMpUserInfo(string $accessToken, string $openid): array
    {
        $url = sprintf(
            'https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN',
            $accessToken,
            $openid
        );

        $response = $this->httpGet($url);
        return json_decode($response, true) ?: [];
    }
} 